package rabid;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StringReader;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import common.IndexWordUtil;
import common.StopWordFile;
import common.UserInteractionException;

/**
 * Communicates with the Index to get the necessary
 * data for each RABID command
 * 
 * @author Andrew Bernard
 */
public class IndexManager {   
  private Index index = null;
  private StopWordFile stopWordFile;
  private IndexWordUtil wordUtil;
  private char[] breakChars;
  private Cluster cluster;
  
  /**
   * Constructor. Creates a new instance of Index and calculates
   * the size of the corpus.
   */
  public IndexManager() throws FileNotFoundException, IOException {
    index = new Index();    
    breakChars = index.getHeader().breakChars.toCharArray();
    wordUtil = new IndexWordUtil(breakChars);
    stopWordFile = new StopWordFile(new File(index.getHeader().stopFilePath), breakChars);  
    setFileSimilarities();    
    cluster = new Cluster(index.getIndexedFiles());
  }
  
  private void setFileSimilarities() {
    Iterator files = index.getIndexedFiles().iterator();
    while(files.hasNext()) {
      IndexedFile indexedFile = (IndexedFile)files.next();
      indexedFile.setSimilarFiles(index.getIndexedFiles());
    }
  }
  
  public List getSimilarFiles(String fileName, int numSimilarFilesToGet) {
    IndexedFile indexedFile = index.getIndexedFile(fileName);
    return indexedFile.getSimilarFiles(numSimilarFilesToGet);
  }
    
  public List browseClusterSet(ClusterSet set) {
    if(set != null) {
      cluster = new Cluster(set.getListOfIndexFiles());
    }
    return cluster.getSets();
  }
  
  public long getCorpusFileSize() {
    return index.getSummary().corpusSize;
  }
  
  public long getIndexFileSize() {
    return index.getHeader().indexFileSize;
  }
  
  public boolean isStopWord(String word) {
    return stopWordFile.isStopWord(word);
  }
    
  public String getCorpusDetails() {
    NumberFormat numberText = NumberFormat.getIntegerInstance();
    StringBuffer stats = new StringBuffer();
    stats.append("\n-------- Corpus Files --------");
    
    Iterator itr = index.getDataHeaderList().iterator();
    while(itr.hasNext()) {
      Index.DataHeader dataHeader = (Index.DataHeader)itr.next();
      stats.append("\n\nFile name: "+dataHeader.fileName)
           .append("\nCharacters: "+numberText.format(dataHeader.charsInFile))
           .append("\nWords: "+numberText.format(dataHeader.wordsInFile));
    }
    
    Index.Summary summary = index.getSummary();
    stats.append("\n-------- Corpus Summary --------")
         .append("\nFiles: " + numberText.format(summary.filesInCorpus))
         .append("\nWords: " + numberText.format(summary.wordsInCorpus))
         .append("\nCharacters: " + numberText.format(summary.charsInCorpus));
    
    return stats.toString();
  }
  
  public String getIndexDetails() {
    StringBuffer details = new StringBuffer();
    Index.Header header = index.getHeader();
    details.append("\n-------- Index Summary --------")
           .append("\nPath: "+header.indexPath)
           .append("\nCreation Date: "+header.creationDate)
           .append("\nStop File Path: "+header.stopFilePath)
           .append("\nCustom break chars: "+header.breakChars)
           .append("\nIndex Size: ")
           .append(NumberFormat.getIntegerInstance().format(header.indexFileSize)).append(" bytes");
    
    return details.toString();
  }
  
  /**
   *    
   * @return 
   */
  public List runQuery(String queryString) 
  throws IOException, UserInteractionException {
    List results = new ArrayList();
    List wordsInQuery = getQueryWords(queryString);
    Query query = new Query(wordsInQuery);
    
    Iterator itrFiles = index.getIndexedFiles().iterator();
    while(itrFiles.hasNext()) {
      IndexedFile indexedFile = (IndexedFile)itrFiles.next();
      if(query.evaluate(indexedFile)) {
        results.add(indexedFile.getFileName());
      }
    }
    return results;
  }
      
  /**
   * Returns a list of the words in the query as string objects.
   */
  private List getQueryWords(String query) 
  throws IOException, UserInteractionException {
    ArrayList words = new ArrayList();
    StringReader reader = new StringReader(query);
    for(String wordText = wordUtil.getNextWord(reader);
        wordText != null;
        wordText = wordUtil.getNextWord(reader)) {
      words.add(wordText);
    }    
    return words;
  }
}
